package com.danieltoms.gcSync.google.feed;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Hashtable;
import java.util.Vector;

import javax.microedition.io.HttpConnection;

import net.rim.device.api.xml.jaxp.XMLWriter;
import net.rim.device.api.xml.parsers.DocumentBuilder;
import net.rim.device.api.xml.parsers.DocumentBuilderFactory;
import net.rim.device.api.xml.parsers.ParserConfigurationException;
import net.rim.device.api.xml.parsers.SAXParser;
import net.rim.device.api.xml.parsers.SAXParserFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.danieltoms.gcSync.GcSyncStore;
import com.danieltoms.gcSync.contact.BBContact;
import com.danieltoms.gcSync.google.GoogleContact;
import com.danieltoms.gcSync.google.GoogleLoginException;
import com.danieltoms.gcSync.util.DateUtil;
import com.danieltoms.io.HttpConnectionHelper;

public class GoogleContactFeed
{

	private int _startIndex = 1;
	private int _totalResults = 1;
	private int _itemsPerPage = 0;
	private Date _updatedDate = null;
	private String _updatedDateString = null;
	private String _lastUpdatedDate = null;

	public GoogleContactFeed(String lastSync)
	{

		if (lastSync != null && lastSync.equals(""))
			lastSync = null;

		_lastUpdatedDate = lastSync;
	}

	public int getTotalResults()
	{
		return _totalResults;
	}

	public Date getUpdated()
	{
		return _updatedDate;
	}

	public String getUpdatedString()
	{
		return _updatedDateString;
	}

	protected String getFeedURL(int startIndex)
	{
		StringBuffer buf = new StringBuffer();
		buf.append("http://www.google.com/m8/feeds/contacts/");
		buf.append(GcSyncStore.instance().getEmail());
		buf.append("/base?start-index=");
		buf.append(new Integer(startIndex).toString());
		// buf.append("&showdeleted");
		if (_lastUpdatedDate != null)
		{
			log("adding last updated date: " + _lastUpdatedDate);
			buf.append("&updated-min=" + _lastUpdatedDate);
		}
		return buf.toString();
	}

	static class PrepareRequest implements HttpConnectionHelper.Callback
	{

		private static final String EN_US = "en-US";
		private static final String ACCEPT_LANGUAGE = "Accept_Language";
		private static final String MIDP1 = "Profile/MIDP-1.0 Configuration/CLDC-1.0";
		private static final String USER_AGENT = "User-Agent";
		public static final Hashtable m_args = new Hashtable();

		public void prepareRequest(String originalURL, HttpConnection conn) throws IOException
		{

			conn.setRequestMethod(HttpConnection.GET);
			conn.setRequestProperty(USER_AGENT, MIDP1);
			conn.setRequestProperty(ACCEPT_LANGUAGE, EN_US);

			conn.setRequestProperty("Authorization", "GoogleLogin auth=" + m_args.get("auth"));

		}

		public void preparePost(HttpConnection c) throws IOException
		{
		}

	}

	private PrepareRequest m_prepareRequest = new PrepareRequest();

	protected InputStream getFeedInputStream(int startIndex) throws GoogleLoginException, IOException
	{

		HttpConnection c = null;
		InputStream is = null;

		int rc = -1;

		m_prepareRequest.m_args.put("auth", GcSyncStore.instance().getAuthToken());

		c = HttpConnectionHelper.connect(getFeedURL(startIndex), m_prepareRequest);

		rc = c.getResponseCode();
		System.out.println("getFeedInputStream return code: " + rc);

		if (rc == HttpConnection.HTTP_UNAUTHORIZED)
		{
			// our auth token expired, login again and try a new one

			GoogleClientLoginFeed gcl = new GoogleClientLoginFeed();
			if (gcl.authenticate(GcSyncStore.instance().getEmail(), GcSyncStore.instance().getPassword()))
			{
				// try again
				m_prepareRequest.m_args.put("auth", GcSyncStore.instance().getAuthToken());

				c = HttpConnectionHelper.connect(getFeedURL(startIndex), m_prepareRequest);

				rc = c.getResponseCode();
				System.out.println("getFeedInputStream return code: " + rc);
				// if we fail again, our password must have changed
			}
		}

		if (rc != 200)
			throw new IOException("Feed returned HTTP " + rc);

		is = c.openDataInputStream();

		return is;

	}

	public void printAllContacts() throws IOException
	{
		try
		{
			InputStream is = this.getFeedInputStream(1);

			if (is != null)
			{

				// Build a document based on the XML file.
				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

				XMLWriter writer = new XMLWriter(System.out);
				writer.setPrettyPrint();
				SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
				parser.parse(is, writer);

			}
			else
				System.out.println("InputStream was null");
		}
		catch (Exception e)
		{
			System.out.println("Exception: " + e);
		}
	}

	public Vector fetchGoogleContacts() throws GoogleLoginException, IOException, ParserConfigurationException,
	        SAXException
	{
		Document document = null;
		NodeList nl = null;

		if (_startIndex > _totalResults) {

		return null;

		}

		Vector v = new Vector();

		InputStream is = this.getFeedInputStream(_startIndex);

		if (is == null)
			return null;

		// Build a document based on the XML file.
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();

		document = builder.parse(is);

		// get items per page
		nl = document.getElementsByTagName("openSearch:itemsPerPage");

		_itemsPerPage = Integer.parseInt(nl.item(0).getFirstChild().getNodeValue());

		// increment out next start
		_startIndex += _itemsPerPage;

		nl = document.getElementsByTagName("openSearch:totalResults");

		// need the total results so to know when to stop
		_totalResults = Integer.parseInt(nl.item(0).getFirstChild().getNodeValue());

		nl = document.getElementsByTagName("updated");

		_updatedDateString = nl.item(0).getFirstChild().getNodeValue();
		_updatedDate = DateUtil.parseRFC3339(_updatedDateString);

		nl = document.getElementsByTagName("entry");

		int length = nl.getLength();
		System.out.println("Number of entries: " + length);

		int i = 0;

		while (i < length)
		{
			Element n = (Element) nl.item(i);

			// add these namespaces so we can update later.
			n.setAttribute("xmlns", "http://www.w3.org/2005/Atom");
			n.setAttribute("xmlns:gContact", "http://schemas.google.com/contact/2008");
			n.setAttribute("xmlns:gd", "http://schemas.google.com/g/2005");
			GoogleContact c = new GoogleContact(n);
			v.addElement(c);

			i++;
		}

		return v;
	}

	public void log(String log)
	{
		System.out.println(log);
	}

	public void createGoogleContact(BBContact bc)
	{
		log("Create new google contact name: " + bc.getGivenName());
		log("Create new google contact email: " + bc.getEmail());

	}

}
